﻿<%@ WebHandler Language="C#" Class="ApsInfiniteCapacity" %>

using System;
using System.Web;
using BusinessRule.DTO;
using BusinessRule.Business;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Web.SessionState;
using System.Data;
using System.Text;
using DatabaseAccess.DBUtility;
using StackExchange.Redis;
using BusinessRule.Common;
using System.Linq;

public class ApsInfiniteCapacity : IHttpHandler, IRequiresSessionState
{
    private InfiniteCapacityBusiness m_ICObj = new InfiniteCapacityBusiness();
    CurrentUserInfo m_UserInfo;
    RedisHelper redis = new RedisHelper();
    string redis_Lock = "MESAPP_InfiniteResLoadPage_Lock";//redis的key值
    public void ProcessRequest(HttpContext context)
    {
        try
        {
            string action = context.Request["action"].ToString();
            m_UserInfo = (CurrentUserInfo)context.Session["CurrentUserInfo"];
            if (m_UserInfo == null)
            {
                context.Response.Write(JsonConvert.SerializeObject(new uMESProcessResult() { Result = false, Message = "登录过期，请重新登录" }));
                return;
            }
            redis_Lock = string.Format("{0}_{1}", redis_Lock, m_UserInfo.EmployeeID);//KEY值要唯一
            switch (action)
            {
                case "searchData":
                    SearchData(context);
                    break;
                case "getContainerInfiniteAps":
                    GetContainerInfiniteAps(context);
                    break;
                case "positiveCalculate":
                    PositiveCalculate(context);
                    break;
                case "reverseCalculate":
                    ReverseCalculate(context);
                    break;
                case "getStepInfiniteAps":
                    GetStepInfiniteAps(context);
                    break;
                case "adjustInfiniteAps"://调整排产结果
                    AdjustInfiniteAps(context);
                    break;
                case "GetAllApsResourceLoadData"://获取所有设备的负荷数据 add by zhangrj 20250805
                    GetAllApsResourceLoadData(context);
                    break;
                case "GetResourceLoadDetail"://获取设备的负荷明细 add by zhangrj 20250807
                    GetResourceLoadDetail(context);
                    break;
                case "GetResourceBarApsDetail"://获取设备明细柱状图的排产明细 add by zhangrj 20250815
                    GetResourceBarApsDetail(context);
                    break;
                case "ExportOverTimeApsData"://导出无限排产超期数据 add by zhangrj 20250915
                    ExportOverTimeApsData(context);
                    break;
                default:
                    break;
            }
        }
        catch (Exception e)
        {
            var result = new uMESProcessResult()
            {
                Result = false,
                Message = e.Message
            };
            context.Response.Write(JsonConvert.SerializeObject(result));
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

    /// <summary>
    /// 导出无限超期数据 add by zhangrj 20250915
    /// </summary>
    /// <param name="context"></param>
    private void ExportOverTimeApsData(HttpContext context)
    {
        StringBuilder sqlBl = new StringBuilder();
        sqlBl.Append(@"SELECT c.mfgordername 订单号,c.productname 零件号,c.containername 批次号,ai.starttime 排产开始时间,ai.endtime 排产结束时间,
                        m.plannedstartdate 订单开始时间,m.plannedcompletiondate 订单结束时间
                        FROM apsplaninfo ai
                        LEFT JOIN containercurrentinfo c ON c.containerid = ai.containerid
                        LEFT JOIN mfgorder m ON m.mfgorderid = c.mfgorderid
                        WHERE ai.apstype2 = '1' 
                        AND ai.endtime > to_date(TO_CHAR(m.plannedcompletiondate,'YYYY-MM-DD') || ' 23:59:59','YYYY-MM-DD hh24:mi:ss')");
        if (!string.IsNullOrWhiteSpace(context.Request.Form["containerName"].ToString()))
        {
            sqlBl.AppendFormat(" AND c.containername LIKE '%{0}%'", context.Request.Form["containerName"].ToString());
        }

        if (!string.IsNullOrWhiteSpace(context.Request.Form["productName"].ToString()))
        {
            sqlBl.AppendFormat(" AND c.productname LIKE '%{0}%'", context.Request.Form["productName"].ToString());
        }

        if (!string.IsNullOrWhiteSpace(context.Request.Form["mfgorderName"].ToString()))
        {
            sqlBl.AppendFormat(" AND c.mfgordername LIKE '%{0}%'", context.Request.Form["mfgorderName"].ToString());
        }

        if (!string.IsNullOrWhiteSpace(context.Request.Form["factoryId"].ToString()))
        {
            sqlBl.AppendFormat(" AND c.originalfactoryid = '{0}'", context.Request.Form["factoryId"].ToString());
        }

        if (!string.IsNullOrWhiteSpace(context.Request.Form["orderStartDate"].ToString()))
        {
            sqlBl.AppendFormat(" AND m.plannedstartdate >= to_date('{0}','YYYY-MM-DD')", context.Request.Form["orderStartDate"].ToString());
        }
        if (!string.IsNullOrWhiteSpace(context.Request.Form["orderEndDate"].ToString()))
        {
            sqlBl.AppendFormat(" AND m.plannedcompletiondate <= to_date('{0}','YYYY-MM-DD')", context.Request.Form["orderEndDate"].ToString());
        }
        DataTable dtAps = DatabaseHelper.Query_ReturnDatTable(sqlBl.ToString());
        byte[] bytes = uLMS_CommonFunction.DataTableExportToExcel(dtAps);
        context.Response.Clear();
        context.Response.Buffer = true;
        context.Response.ClearHeaders();
        context.Response.ClearContent();
        context.Response.ContentType = "application/vnd.ms-excel";
        context.Response.AddHeader("fileDownload", "1");
        context.Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}{1}.xls", context.Server.UrlEncode("无限产能排产超期记录"), DateTime.Now.ToString("yyyyMMddHHmmssffff")));
        context.Response.AddHeader("Content-Length", bytes.Length.ToString());
        context.Response.AddHeader("Content-Type", "UTF-8");
        context.Response.Charset = "UTF-8";
        context.Response.ContentEncoding = Encoding.UTF8;
        context.Response.BinaryWrite(bytes);
        context.Response.Flush();
        context.Response.Close();
    }
    
    /// <summary>
    /// 获取设备明细柱状图的排产明细 add by zhangrj 20250815
    /// </summary>
    /// <param name="context"></param>
    private void GetResourceBarApsDetail(HttpContext context)
    {
        uMESProcessResult result = new uMESProcessResult() { Result = true, Message = "获取成功" };
        if (!redis.ExistsKey(redis_Lock))
        {
            result.Result = false; result.Message = "数据过期，请重新查询";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }
        string resourceID = context.Request["resourceID"].ToString();//设备ID
        string currDate = context.Request["currDate"].ToString();//选择的柱状图日期
        List<ResourceLoad> list = JsonConvert.DeserializeObject<List<ResourceLoad>>(redis.GetSetValues(redis_Lock)[0]);//读取缓存
        ResourceLoad resLoad = list.Where(p => p.ResourceID == resourceID).FirstOrDefault();//找到该设备的数据
        if (resLoad == null)
        {
            result.Result = false; result.Message = "未查询到该设备的负荷明细";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }
        if (resLoad.DayLoad.Count == 0)
        {
            result.Result = false; result.Message = "暂无明细";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }
        DayLoad dl = resLoad.DayLoad.Where(p => p.DayDate == currDate).FirstOrDefault();//找到该日期的明细
        if (dl == null)
        {
            result.Result = false; result.Message = "暂无该日期的明细";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }
        result.ReturnData = dl.DayLoadApsPlanDetail;
        context.Response.Write(JsonConvert.SerializeObject(result));
    }

    /// <summary>
    /// 获取设备的负荷明细（柱状图）add by zhangrj 20250807
    /// </summary>
    /// <param name="context"></param>
    private void GetResourceLoadDetail(HttpContext context)
    {
        uMESProcessResult result = new uMESProcessResult() { Result = true, Message = "获取成功" };
        if (!redis.ExistsKey(redis_Lock))
        {
            result.Result = false; result.Message = "数据过期，请重新查询";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }
        string resourceID = context.Request["resourceID"].ToString();
        List<ResourceLoad> list = JsonConvert.DeserializeObject<List<ResourceLoad>>(redis.GetSetValues(redis_Lock)[0]);//读取缓存
        ResourceLoad resLoad = list.Where(p => p.ResourceID == resourceID).FirstOrDefault();//找到该设备的数据
        if (resLoad == null)
        {
            result.Result = false; result.Message = "未查询到该设备的负荷明细";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }
        if (resLoad.DayLoad.Count == 0)
        {
            result.Result = false; result.Message = "暂无明细";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }
        result.ReturnData = resLoad.DayLoad;
        context.Response.Write(JsonConvert.SerializeObject(result));
    }

    /// <summary>
    /// 获取所有设备的负荷数据 add by zhangrj 20250805
    /// </summary>
    /// <param name="context"></param>
    private void GetAllApsResourceLoadData(HttpContext context)
    {
        redis.DeleteKey(redis_Lock);//先删除缓存
        uMESProcessResult result = new uMESProcessResult() { Result = true, Message = "获取成功" };
        Dictionary<string, string> dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(context.Request["params"].ToString());//查询参数
        if (string.IsNullOrWhiteSpace(dic["StartDate"]) || string.IsNullOrWhiteSpace(dic["EndDate"]))
        {
            result.Result = false;
            result.Message = "请选择日期范围！";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }
        /*查询数据*/
        StringBuilder sql = new StringBuilder();
        sql.AppendFormat(@"SELECT r.resourcename,r.resourceid,r.description resourcedesc,
                            wc.workcentername,t.teamname,r.workshiftid,ws.workshiftname,0 workshifthours,
                            mc.makecalendarname, '' totalload
                            FROM Resourcedef r 
                            LEFT JOIN workcenter wc ON wc.workcenterid = r.workcenterid
                            LEFT JOIN team t ON t.teamid = r.teamid
                            LEFT JOIN Workshift ws ON ws.workshiftid = r.workshiftid
                            LEFT JOIN makecalendar mc ON mc.makecalendarid = r.makecalendarid
                            WHERE r.factoryid = '{0}' AND r.isuse = 0", m_UserInfo.FactoryID);
        if (dic.ContainsKey("ResourceName") && !string.IsNullOrWhiteSpace(dic["ResourceName"]))
        {
            sql.AppendFormat(" AND r.resourcename = '{0}'", dic["ResourceName"]);
        }
        if (dic.ContainsKey("WorkCenterName") && !string.IsNullOrWhiteSpace(dic["WorkCenterName"]))
        {
            sql.AppendFormat(" AND wc.workcentername = '{0}'", dic["WorkCenterName"]);
        }
        if (dic.ContainsKey("TeamName") && !string.IsNullOrWhiteSpace(dic["TeamName"]))
        {
            sql.AppendFormat(" AND t.teamname = '{0}'", dic["TeamName"]);
        }
        DataTable dtResource = DatabaseHelper.Query_ReturnDatTable(sql.ToString());//查询出需要统计的设备信息
        if (dtResource.Rows.Count == 0)
        {
            result.Result = false;
            result.Message = "未查询到数据！";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }
        /*结束查询，开始计算*/
        DateTime startDate = DateTime.Parse(dic["StartDate"]);//开始日期
        DateTime endDate = DateTime.Parse(dic["EndDate"]);//结束日期
        int days = (int)Math.Ceiling((endDate - startDate).TotalDays + 1);//获取相隔的天数
        List<ResourceLoad> resourceLoadList = new List<ResourceLoad>();//最终的数据
        foreach (DataRow drRes in dtResource.Rows) //循环设备，开始计算每一个设备的负荷
        {
            ResourceLoad rl = GetResourceLoadForDate(drRes["resourceid"].ToString(), drRes["workshiftid"].ToString(), startDate, endDate);//获取设备的排产时长
            drRes["totalload"] = rl.WorkShiftHours == 0 ? 0 : Math.Round((rl.TotalApsHours / (rl.WorkShiftHours * days)) * 100, 2);//计算出该设备总的负荷数
            drRes["workshiftname"] = string.IsNullOrWhiteSpace(drRes["workshiftname"].ToString()) ? "" : string.Format("{0}({1})", drRes["workshiftname"].ToString(), GetWorkShiftDetailString(drRes["workshiftid"].ToString()));
            drRes["workshifthours"] = rl.WorkShiftHours;
            resourceLoadList.Add(rl);
        }
        redis.AddSet(redis_Lock, JsonConvert.SerializeObject(resourceLoadList));//将计算后的值存储到redis
        redis.SetKeyExpiry(redis_Lock, TimeSpan.FromMinutes(20)); // 设定超期时间20分钟
        dtResource.AcceptChanges();
        result.DBTable = dtResource.AsEnumerable().OrderByDescending(p => double.Parse(p["totalload"].ToString())).CopyToDataTable();//排序
        context.Response.Write(JsonConvert.SerializeObject(result));
    }

    /// <summary>
    /// 获取班次明细字符串
    /// </summary>
    /// <param name="workShiftID"></param>
    /// <returns></returns>
    private string GetWorkShiftDetailString(string workShiftID)
    {
        string sql = string.Format(@"SELECT wm_concat( wsd.startdate || '-' || wsd.enddate ) 
                            FROM workshiftdetail wsd WHERE wsd.workshiftid = '{0}'", workShiftID);
        return DatabaseHelper.Query_ReturnDatTable(sql).Rows[0][0].ToString();
    }

    /// <summary>
    /// 获取某一段日期内的设备负荷
    /// </summary>
    /// <param name="resourceID"></param>
    /// <param name="workshiftID"></param>
    /// <param name="startDate"></param>
    /// <param name="endDate"></param>
    /// <returns></returns>
    private ResourceLoad GetResourceLoadForDate(string resourceID, string workshiftID, DateTime startDate, DateTime endDate)
    {
        ResourceLoad rl = new ResourceLoad(resourceID);//初始化数据
        /*-------------------
         * 变量定义，数据赋值
         * ----------------*/
        rl.WorkShiftHours = GetWorkShiftHoursByID(workshiftID);//获取该设备的班次时长
        if (rl.WorkShiftHours == 0)
        {
            return rl;
        }
        /*--------------
         * 开始计算负荷
         * -------------*/
        while (startDate <= endDate) //开始循环每一天，直到最终日期
        {
            DateTime currStartTime = DateTime.Parse(string.Format("{0} 00:00:00", startDate.ToShortDateString()));//当前日期的开始时间
            DateTime currEndTime = DateTime.Parse(string.Format("{0} 23:59:59", startDate.ToShortDateString()));//当前日期的结束时间
            DataTable dtApsRes = DatabaseHelper.Query_ReturnDatTable(GetQueryResourceApsSql(resourceID, currStartTime, currEndTime));
            Tuple<double, List<DayLoadApsPlanDetail>> resData = GetApsResLoadValue(dtApsRes, currStartTime, currEndTime);
            /*------计算完成，记录值------*/
            rl.DayLoad.Add(new DayLoad()
            {
                DayDate = startDate.ToShortDateString(),
                Hours = resData.Item1,
                LoadValue = Math.Round((resData.Item1 / rl.WorkShiftHours) * 100, 2),
                DayLoadApsPlanDetail = resData.Item2
            });//计算当天的负荷值，记录当天的数据
            startDate = startDate.AddDays(1);//下一天
        }
        rl.TotalApsHours = rl.DayLoad.Sum(p => p.Hours);//合计每一天的时长
        return rl;
    }

    /// <summary>
    /// 获取时间段内的设备排产查询SQL
    /// </summary>
    /// <param name="resourceID"></param>
    /// <param name="currStartTime"></param>
    /// <param name="currEndTime"></param>
    /// <returns></returns>
    private string GetQueryResourceApsSql(string resourceID, DateTime currStartTime, DateTime currEndTime)
    {
        return string.Format(@"SELECT Distinct ap.apsplandetailid,ap.starttime,ap.endtime,s.specid,
                        c.containername, c.mfgordername, wb.workflowname || ':' || w.workflowrevision AS workflowinfo,
                        ap.workflowstepname
                        FROM apsplandetail ap 
                        LEFT JOIN apsplaninfo ai ON ai.apsplaninfoid = ap.apsplaninfoid
                        LEFT JOIN workflow w ON w.workflowid = ai.workflowid
                        LEFT JOIN workflowbase wb ON wb.workflowbaseid = w.workflowbaseid
                        LEFT JOIN containercurrentinfo c ON c.containerid = ai.containerid
                        LEFT JOIN workflowstep ws ON ws.workflowstepid = ap.workflowstepid
                        LEFT JOIN specbase sb ON sb.specbaseid = ws.specbaseid
                        LEFT JOIN spec s ON s.specid = NVL(sb.revofrcdid,ws.specid)
                        LEFT JOIN specresourceinfo sp ON sp.specid = s.specid
                        WHERE sp.resourceid = '{0}' 
                        AND (
                           (ap.starttime >= to_date('{1}','yyyy-mm-dd hh24:mi:ss') AND ap.endtime <= to_date('{2}','yyyy-mm-dd hh24:mi:ss'))
                        OR (ap.starttime >= to_date('{1}','yyyy-mm-dd hh24:mi:ss') AND ap.starttime < to_date('{2}','yyyy-mm-dd hh24:mi:ss') AND ap.endtime > to_date('{2}','yyyy-mm-dd hh24:mi:ss'))
                        OR (ap.starttime < to_date('{1}','yyyy-mm-dd hh24:mi:ss') AND ap.endtime > to_date('{1}','yyyy-mm-dd hh24:mi:ss') AND ap.endtime <= to_date('{2}','yyyy-mm-dd hh24:mi:ss'))
                        OR (ap.starttime < to_date('{1}','yyyy-mm-dd hh24:mi:ss') AND ap.endtime > to_date('{2}','yyyy-mm-dd hh24:mi:ss'))
                        )
                        AND ai.apstype2 = 1", resourceID, currStartTime, currEndTime);
    }

    /// <summary>
    /// 计算排产明细负荷值
    /// </summary>
    /// <param name="dtAps"></param>
    /// <param name="currStartTime"></param>
    /// <param name="currEndTime"></param>
    /// <returns></returns>
    private Tuple<double, List<DayLoadApsPlanDetail>> GetApsResLoadValue(DataTable dtAps, DateTime currStartTime, DateTime currEndTime)
    {
        double currHours = 0;//当天的时长
        List<DayLoadApsPlanDetail> apsPlanDetailList = new List<DayLoadApsPlanDetail>(); //当日的排产明细集合
        foreach (DataRow drOR in dtAps.Rows)
        {
            double tHours = 24;//相隔小时
            DateTime st = DateTime.Parse(drOR["starttime"].ToString());
            DateTime et = DateTime.Parse(drOR["endtime"].ToString());
            if (st >= currStartTime && et <= currEndTime) //排产开始时间和结束时间都在当天时间内的数据
            {
                tHours = (et - st).TotalHours;
            }
            else if (st < currStartTime && et > currStartTime && et <= currEndTime) //排产开始时间不在当前时间内，但是排产结束时间是当天时间内的数据
            {
                tHours = (et - currStartTime).TotalHours;
            }
            else if (st >= currStartTime && st < currEndTime && et > currEndTime) //排产开始时间在当前时间内，但是排产结束时间不是当天时间内的数据
            {
                tHours = (currEndTime - st).TotalHours;
            }
            else //当天时间即全天都在排产时间内的数据
            {
                tHours = 24;
            }
            int specResCount = GetSpecResourceCount(drOR["specid"].ToString());//该条排产的工序下的设备数
            double apsHours = specResCount == 0 ? 0 : tHours / (double)specResCount;//当天的时长累加（排产的时长 / 设备数）
            currHours += apsHours;//累加当天的加工时长
            /*记录该排产数据，以备明细查询*/
            apsPlanDetailList.Add(new DayLoadApsPlanDetail()
            {
                ApsPlanDetailID = drOR["apsplandetailid"].ToString(),//排产ID
                ContainerName = drOR["ContainerName"].ToString(),
                MfgOrderName = drOR["MfgOrderName"].ToString(),
                WorkflowInfo = drOR["WorkflowInfo"].ToString(),
                WorkFlowStepName = drOR["WorkFlowStepName"].ToString(),
                StartTime = st,//排产开始时间
                EndTime = et,//排产结束时间
                ResPercentage = string.Format("{0}%", (Math.Round(1.00 / specResCount, 2) * 100)),//设备占比
                ResWorkTimeHours = apsHours //记录设备在当前时间段内的加工时长
            });
        }
        apsPlanDetailList.ForEach(p => p.ResWorkTimeHours = Math.Round(p.ResWorkTimeHours, 2));
        return new Tuple<double, List<DayLoadApsPlanDetail>>(currHours, apsPlanDetailList);
    }

    /// <summary>
    /// 获取工序下的设备数量
    /// </summary>
    /// <param name="specID"></param>
    /// <returns></returns>
    private int GetSpecResourceCount(string specID)
    {
        string sql = string.Format(@"SELECT COUNT(1) FROM specresourceinfo sp 
                    LEFT JOIN resourcedef r ON r.resourceid = sp.resourceid
                    WHERE sp.specid = '{0}' AND r.isuse = 0", specID);
        return int.Parse(DatabaseHelper.Query_ReturnDatTable(sql).Rows[0]["COUNT(1)"].ToString());
    }

    /// <summary>
    /// 获取班次的时长（小时）
    /// </summary>
    /// <param name="workShiftID"></param>
    /// <returns></returns>
    private double GetWorkShiftHoursByID(string workShiftID)
    {
        string sql = string.Format(@"SELECT wsd.startdate,wsd.enddate,wsd.mins FROM Workshift ws
                        LEFT JOIN Workshiftdetail wsd ON wsd.workshiftid = ws.workshiftid
                        WHERE ws.workshiftid = '{0}' AND ws.isuse = 0", workShiftID);
        DataTable dtWorkShift = DatabaseHelper.Query_ReturnDatTable(sql);
        double hours = 0;//计算出最终的时长
        foreach (DataRow item in dtWorkShift.Rows)
        {
            if (string.IsNullOrWhiteSpace(item["mins"].ToString())) //如果为空，则计算出时长
            {
                DateTime start = DateTime.Parse(item["startdate"].ToString());
                DateTime end = DateTime.Parse(item["enddate"].ToString());
                TimeSpan ts = end - start;
                hours += ts.TotalMinutes / (double)60;
                continue;
            }
            hours += (double.Parse(item["mins"].ToString()) / (double)60);
        }
        return hours;
    }

    /// <summary>
    /// 调整排产结果
    /// </summary>
    /// <param name="context"></param>
    public void AdjustInfiniteAps(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        uMESProcessResult result = new uMESProcessResult();
        result.Result = false;

        if (!string.IsNullOrWhiteSpace(context.Request["conAps"].ToString()))
        {
            var conAps = JsonConvert.DeserializeObject<DataTable>(context.Request["conAps"].ToString());
            if (conAps.Rows.Count == 0)
            {
                result.Message = "无参数";
                context.Response.Write(JsonConvert.SerializeObject(result));
                return;
            }
            Dictionary<string, string> para = new Dictionary<string, string>();
            para["MakeCalendarID"] = "123";
            para["EmployeeID"] = m_UserInfo.EmployeeID.ToString();

            m_ICObj.AdjustInfiniteCalculate(conAps, para);
        }
        else
        {
            result.Message = "无参数";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }


        result.Result = true;
        context.Response.Write(JsonConvert.SerializeObject(result));
    }

    /// <summary>
    /// 获取工序的排产计划
    /// </summary>
    /// <param name="context"></param>
    public void GetStepInfiniteAps(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        uMESProcessResult result = new uMESProcessResult();
        result.Result = false;

        Dictionary<string, string> para = new Dictionary<string, string>();
        if (!string.IsNullOrWhiteSpace(context.Request["param"].ToString()))
        {
            DataTable param = JsonConvert.DeserializeObject<DataTable>(context.Request["param"].ToString());
            if (param.Rows.Count > 0)
            {
                foreach (DataRow r in param.Rows)
                {
                    if (para.ContainsKey("ApsPlanInfoIDs"))
                    {
                        para["ApsPlanInfoIDs"] += "'" + r["ApsPlanInfoID"].ToString() + "',";
                    }
                    else
                    {
                        para.Add("ApsPlanInfoIDs", "'" + r["ApsPlanInfoID"].ToString() + "',");
                    }
                }
                para["ApsPlanInfoIDs"] = para["ApsPlanInfoIDs"].TrimEnd(',');
            }
        }

        if (para.Keys.Count == 0)
        {
            result.Message = "参数无效";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }

        DataTable dt = m_ICObj.GetStepInfiniteAps(para);

        if (dt.Rows.Count == 0)
        {
            result.Message = "无数据";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }

        Dictionary<string, object> apsData = new Dictionary<string, object>();
        List<Dictionary<string, object>> returnData = new List<Dictionary<string, object>>();

        DataTable conDt = dt.DefaultView.ToTable(true, "apsplaninfoid", "constarttime", "conendtime", "containername", "ApsType", "containerid", "workflowid");//批次级计划

        foreach (DataRow con in conDt.Rows)
        {
            apsData = new Dictionary<string, object>();
            apsData["id"] = con["apsplaninfoid"].ToString();
            apsData["name"] = con["containername"].ToString();

            List<Dictionary<string, object>> conperiods = new List<Dictionary<string, object>>();
            Dictionary<string, object> conPeriod = new Dictionary<string, object>();
            var conStart = con["constarttime"].ToString();//uLMS_CommonFunction.GetMsStamp(DateTime.Parse(con["constarttime"].ToString()));
            var conEnd = con["conendtime"].ToString();// uLMS_CommonFunction.GetMsStamp(DateTime.Parse(con["conendtime"].ToString())); 
            conPeriod["id"] = Guid.NewGuid().ToString();

            conPeriod["text"] = con["containername"].ToString();
            conPeriod["start"] = conStart;
            conPeriod["end"] = conEnd;
            conPeriod["fill"] = "#5FB878";

            conperiods.Add(conPeriod);

            apsData["periods"] = conperiods;
            //批次级个性化属性
            Dictionary<string, object> conCustomData = new Dictionary<string, object>();
            conCustomData["differ"] = 0;//调整的差值
            conCustomData["constarttime"] = conStart;
            conCustomData["conendtime"] = conEnd;
            conCustomData["apsType"] = con["apsType"].ToString();
            conCustomData["containerid"] = con["containerid"].ToString();
            conCustomData["workflowid"] = con["workflowid"].ToString();

            apsData["customData"] = conCustomData;

            returnData.Add(apsData);

            //工序级信息
            DataRow[] steps = dt.Select("apsplaninfoid='" + con["apsplaninfoid"].ToString() + "'");

            foreach (DataRow stepAps in steps)
            {
                Dictionary<string, object> stepApsData = new Dictionary<string, object>();

                stepApsData["id"] = stepAps["apsplandetailid"].ToString();
                stepApsData["name"] = stepAps["workflowstepname"].ToString();
                List<Dictionary<string, object>> periods = new List<Dictionary<string, object>>();
                Dictionary<string, object> period = new Dictionary<string, object>();
                period["id"] = Guid.NewGuid().ToString();
                period["text"] = stepAps["workflowstepname"].ToString();
                period["start"] = stepAps["stepstarttime"].ToString();// uLMS_CommonFunction.GetMsStamp(DateTime.Parse(stepAps["stepstarttime"].ToString()));
                period["end"] = stepAps["stependtime"].ToString();//uLMS_CommonFunction.GetMsStamp(DateTime.Parse(stepAps["stependtime"].ToString())); 

                periods.Add(period);

                //测试，添加假期
                //if (stepAps["workflowstepname"].ToString() == "50-工序50")
                //{
                //    period = new Dictionary<string, object>();
                //    period["id"] = Guid.NewGuid().ToString();
                //    period["text"] = "假期";
                //    period["start"] = "2022/4/30 0:00:00";
                //    period["end"] = "2022/5/4 0:00:00";
                //    period["customData"] = new Dictionary<string, string>() { { "isHolidate", "1" } };
                //    periods.Add(period);
                //}                

                stepApsData["periods"] = periods;
                stepApsData["parent"] = con["apsplaninfoid"].ToString();

                returnData.Add(stepApsData);
            }

        }


        result.ReturnData = JsonConvert.SerializeObject(returnData);
        //result.DBTable = dt;
        result.Result = true;
        context.Response.Write(JsonConvert.SerializeObject(result));
    }

    /// <summary>
    /// 倒排计算
    /// </summary>
    /// <param name="context"></param>
    public void ReverseCalculate(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        uMESProcessResult result = new uMESProcessResult();
        result.Result = false;

        Dictionary<string, string> para = new Dictionary<string, string>();
        para["MakeCalendarID"] = "123";
        para["EmployeeID"] = m_UserInfo.EmployeeID.ToString();

        DataTable conDt = new DataTable();
        if (!string.IsNullOrWhiteSpace(context.Request.Form["containers"].ToString()))
        {
            conDt = JsonConvert.DeserializeObject<DataTable>(context.Request.Form["containers"].ToString());
        }
        else
        {
            result.Message = "无效参数";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }

        m_ICObj.ReverseCalculate(conDt, para);
        //计算完成之后重载加载正排的数据
        DataTable positiveDt = m_ICObj.GetContainerInfiniteAps(conDt, "2");

        result.Result = true;
        result.ReturnData = positiveDt;
        context.Response.Write(JsonConvert.SerializeObject(result));
    }

    /// <summary>
    /// 正排计算
    /// </summary>
    /// <param name="context"></param>
    public void PositiveCalculate(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        uMESProcessResult result = new uMESProcessResult();
        result.Result = false;

        Dictionary<string, string> para = new Dictionary<string, string>();
        para["MakeCalendarID"] = "123";
        para["EmployeeID"] = m_UserInfo.EmployeeID.ToString();
        para["FactoryID"] = m_UserInfo.FactoryID;

        DataTable conDt = new DataTable();
        if (!string.IsNullOrWhiteSpace(context.Request.Form["containers"].ToString()))
        {
            conDt = JsonConvert.DeserializeObject<DataTable>(context.Request.Form["containers"].ToString());
        }
        else
        {
            result.Message = "无效参数";
            context.Response.Write(JsonConvert.SerializeObject(result));
            return;
        }

        m_ICObj.PositiveCalculate(conDt, para);
        //计算完成之后重载加载正排的数据
        DataTable positiveDt = m_ICObj.GetContainerInfiniteAps(conDt, "1");

        result.Result = true;
        result.ReturnData = positiveDt;
        context.Response.Write(JsonConvert.SerializeObject(result));
    }

    /// <summary>
    /// 查询获取列表
    /// </summary>
    /// <param name="context"></param>
    public void SearchData(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        uMESProcessResult result = new uMESProcessResult();
        result.Result = false;

        Dictionary<string, string> para = new Dictionary<string, string>();

        para.Add("CurrentPageIndex", context.Request.Form["pageNumber"].ToString());//页码
        para.Add("PageSize", context.Request.Form["pageSize"].ToString());//每页页数

        if (!string.IsNullOrWhiteSpace(context.Request.Form["containerName"].ToString()))
        {
            para.Add("ContainerName", context.Request.Form["containerName"].ToString());
        }

        if (!string.IsNullOrWhiteSpace(context.Request.Form["productName"].ToString()))
        {
            para.Add("ProductName", context.Request.Form["productName"].ToString());
        }

        if (!string.IsNullOrWhiteSpace(context.Request.Form["mfgorderName"].ToString()))
        {
            para.Add("MfgorderName", context.Request.Form["mfgorderName"].ToString());
        }

        if (!string.IsNullOrWhiteSpace(context.Request.Form["factoryId"].ToString()))
        {
            para.Add("FactoryID", context.Request.Form["factoryId"].ToString());
        }

        if (!string.IsNullOrWhiteSpace(context.Request.Form["orderStartDate"].ToString()))
        {
            para.Add("OrderStartDate", context.Request.Form["orderStartDate"].ToString());
        }

        if (!string.IsNullOrWhiteSpace(context.Request.Form["orderEndDate"].ToString()))
        {
            para.Add("OrderEndDate", context.Request.Form["orderEndDate"].ToString());
            if (para.ContainsKey("OrderStartDate"))
            {
                if (DateTime.Parse(para["OrderStartDate"]) > DateTime.Parse(para["OrderEndDate"]))
                {
                    result.Result = false;
                    result.Message = "开始日期大于结束日期";
                    context.Response.Write(JsonConvert.SerializeObject(result));
                    return;
                }
            }
        }
        //para.Add("FactoryID", m_UserInfo.FactoryID);
        result = m_ICObj.GetContainerInfo(para);
        context.Response.Write(JsonConvert.SerializeObject(result));
    }


    /// <summary>
    /// 查询批次排产信息
    /// </summary>
    /// <param name="context"></param>
    public void GetContainerInfiniteAps(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        uMESProcessResult result = new uMESProcessResult();
        result.Result = false;

        DataTable paraDt = JsonConvert.DeserializeObject<DataTable>(context.Request.Form["containerPara"]);

        DataTable apsDt = m_ICObj.GetContainerInfiniteAps(paraDt);

        Dictionary<string, object> apsPara = new Dictionary<string, object>();
        apsPara["positiveInfo"] = null; apsPara["reverseInfo"] = null;

        if (apsDt.Select("ApsType=1").Length > 0)
        {
            apsPara["positiveInfo"] = apsDt.Select("ApsType=1").CopyToDataTable();
        }

        if (apsDt.Select("ApsType=2").Length > 0)
        {
            apsPara["reverseInfo"] = apsDt.Select("ApsType=2").CopyToDataTable();
        }

        result.Result = true;
        result.ReturnData = apsPara;
        context.Response.Write(JsonConvert.SerializeObject(result));

    }

    /// <summary>
    /// 设备负荷
    /// </summary>
    private class ResourceLoad
    {
        public ResourceLoad()
        {
            WorkShiftHours = 0;
            TotalApsHours = 0;
            DayLoad = new List<DayLoad>();
        }
        public ResourceLoad(string resourceID)
        {
            ResourceID = resourceID;
            WorkShiftHours = 0;
            TotalApsHours = 0;
            DayLoad = new List<DayLoad>();
        }
        /// <summary>
        /// 设备ID
        /// </summary>
        public string ResourceID { get; set; }
        /// <summary>
        /// 设备班次时长
        /// </summary>
        public double WorkShiftHours { get; set; }
        /// <summary>
        /// 设备排产总的占用时长（小时）
        /// </summary>
        public double TotalApsHours { get; set; }
        /// <summary>
        /// 设备每一天的负荷明细
        /// </summary>
        public List<DayLoad> DayLoad { get; set; }
    }
    /// <summary>
    /// 设备负荷明细
    /// </summary>
    private class DayLoad
    {
        public DayLoad()
        {
            DayLoadApsPlanDetail = new List<DayLoadApsPlanDetail>();
        }
        /// <summary>
        /// 日期
        /// </summary>
        public string DayDate { get; set; }
        /// <summary>
        /// 当前日期时长
        /// </summary>
        public double Hours { get; set; }
        /// <summary>
        /// 负荷值
        /// </summary>
        public double LoadValue { get; set; }
        /// <summary>
        /// 该设备的在该日期下的所有排产明细ID
        /// </summary>
        public List<DayLoadApsPlanDetail> DayLoadApsPlanDetail { get; set; }
    }

    private class DayLoadApsPlanDetail
    {
        /// <summary>
        /// 排产明细ID
        /// </summary>
        public string ApsPlanDetailID { get; set; }
        /// <summary>
        /// 批次号
        /// </summary>
        public string ContainerName { get; set; }
        /// <summary>
        /// 订单号
        /// </summary>
        public string MfgOrderName { get; set; }
        /// <summary>
        /// 工艺信息
        /// </summary>
        public string WorkflowInfo { get; set; }
        /// <summary>
        /// 工序
        /// </summary>
        public string WorkFlowStepName { get; set; }
        /// <summary>
        /// 排产开始时间
        /// </summary>
        public DateTime StartTime { get; set; }
        /// <summary>
        /// 排产结束时间
        /// </summary>
        public DateTime EndTime { get; set; }
        /// <summary>
        /// 该排产设备占比（百分比）
        /// </summary>
        public string ResPercentage { get; set; }
        /// <summary>
        /// 该排产设备加工时长
        /// </summary>
        public double ResWorkTimeHours { get; set; }
    }
}